package practica1.ui.tablaPoblacion;

import java.awt.Point;
import java.util.HashMap;
import javax.swing.table.AbstractTableModel;
import practica1.util.HashCodeUtil;

/**
 * Clase que extiende de AbstractTablaModel e implementa las funciones
 * para manejar el modelo de la tabla
 * @author Miguel González - Miguel
 */
public class ModeloPoblacionTabla extends AbstractTableModel {

    private HashMap<Point, String> lookup;
    private final int rows;
    private final int columns;
    private String headers[];

    /**
     * Constructor por defecto del modelo de la tabla
     * @param datos Array bidimensional que contiene todos los datos
     * @param columnHeaders Cabeceras de las columnas
     */
    public ModeloPoblacionTabla(String datos[][], String columnHeaders[]) {
        lookup = new HashMap<Point, String>();

        //Rellenamos los datos
        for (int i = 0; i < datos.length; i++) {
            for (int j = 0; j < datos[i].length; j++) {
                lookup.put(new Point(i, j), datos[i][j]);
            }
        }

        this.rows = datos.length;
        this.columns = columnHeaders.length;

        headers = new String[columnHeaders.length];
        System.arraycopy(
                columnHeaders, 0, headers, 0, columnHeaders.length);
    }
    
    /**
     * Compara un objeto con el modelo de la tabla
     * @param poblacionTabla Object ModeloTabla
     * @return Devuelve verdad si el objeto es un modelo de la tabla igual, sino falso
     */
    @Override
    public boolean equals(Object poblacionTabla) {
        boolean columnasIguales = true;
        if(poblacionTabla != null) {
            if(poblacionTabla instanceof ModeloPoblacionTabla) {
                ModeloPoblacionTabla p = (ModeloPoblacionTabla) poblacionTabla;
                
                if(p.getColumnCount() == columns && p.getRowCount() == rows) {
                    for(int i=0 ; i<columns; i++) {
                        if(!p.getColumnName(i).equals(headers[i])) {
                            columnasIguales = false;
                        }
                    }
                }
            }
        }
        
        if(columnasIguales) {
            ModeloPoblacionTabla p = (ModeloPoblacionTabla) poblacionTabla;
            //Comprobamos si tienen los mismos datos
            for(int i=0; i<rows; i++) {
                for(int j=0; j<columns; j++) {
                    Point point = new Point(i, j);
                    //Si no es el mismo dato devolvemos false
                    if(!lookup.get(point).equals(p.getValueAt(i, j))) {
                        return false;
                    }
                }
            }
            
            return true;
        }
        
        return false;
    }
    
    /**
     * Devuelve el hashCode del modelo de la tabla
     * @return int hashCode
     */
    @Override
    public int hashCode() {
        int result = HashCodeUtil.SEED;
        
        result = HashCodeUtil.hash(result, rows);
        result = HashCodeUtil.hash(result, columns);
        result = HashCodeUtil.hash(result, headers);
        for(int i=0; i<rows; i++) {
            for(int j=0; j<columns; j++) {
                result = HashCodeUtil.hash(result, lookup.get(new Point(i, j)));
            }
        }
        
        return result;
    }

    @Override
    public ModeloPoblacionTabla clone() {
        String datos[][] = new String[rows][columns];
        
        for(int i=0; i<rows; i++) {
            for(int j=0; j<columns; j++) {
                datos[i][j] = lookup.get(new Point(i, j));
            }
        }
        
        ModeloPoblacionTabla mod = new ModeloPoblacionTabla(datos, headers);
        
        return mod;
    }
    
    /**
     * Devuelve numero de columnas
     * @return numero de columnas
     */
    @Override
    public int getColumnCount() {
        return columns;
    }

    /**
     * Devuelve numero de filas
     * @return numero de filas
     */
    @Override
    public int getRowCount() {
        return rows;
    }

    /**
     * Devuelve el nombre de la columna
     * @param column numero de columna
     * @return nombre de la columna
     */
    @Override
    public String getColumnName(int column) {
        return headers[column];
    }

    /**
     * Devuelve el valor de una posicion
     * @param row numero de columna
     * @param column numero de fila
     * @return posicion
     */
    @Override
    public Object getValueAt(int row, int column) {
        return lookup.get(new Point(row, column));
    }

    /**
     * Introduce un dato en una posicion
     * @param value Valor a introducir
     * @param row Fila del dato
     * @param column Columna del dato
     */
    public void setValueAt(String value, int row, int column) {
        if ((rows < 0) || (columns < 0)) {
            throw new IllegalArgumentException("Invalid row/column setting");
        }
        if ((row < rows) && (column < columns)) {
            lookup.put(new Point(row, column), value.toString());
        }
        
        super.fireTableDataChanged();
    }
    
    public void setDosisComida(String[] dosisComida) {
        for(int i=0; i<rows; i++) {
            lookup.put(new Point(i, 4), dosisComida[i]);
        }
        
        super.fireTableDataChanged();
    }

    /**
     * Devuelve si una celda es editable o no
     * @param row Fila de la celda
     * @param col Columna de la celda
     * @return Devuelve falso si es la columna 0, sino verdad
     */
    @Override
    public boolean isCellEditable(int row, int col) {
        return col != 0;
    }
}
